#ifndef __OBJECT_HANDLER_FACTORY_HPP__
#define __OBJECT_HANDLER_FACTORY_HPP__

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <string>
#include <map>

#include <SmegTools/Pattern/Singleton.hpp>

class BaseObjectHandler;

////////////////////////////////////////////////////////////
/// Factory of ObjectHandler
////////////////////////////////////////////////////////////
class ObjectHandlerFactory : public smeg::tools::Singleton< ObjectHandlerFactory >
{
    DECLARE_SINGLETON( ObjectHandlerFactory )

public:
    ////////////////////////////////////////////////////////////
    /// Initialize the factory
    ///
    /// \return Whether the initialization went successfully
    ///
    ////////////////////////////////////////////////////////////
    bool                            Init();
        
    ////////////////////////////////////////////////////////////
    /// Add an object handler
    ///
    /// \param _ObjectHandlerName : Name of the object handler
    /// \param _ObjectHandler : Handler to copy
    /// \param _bForce : Whether to force the add (if the named handler already exists)
    ///
    ////////////////////////////////////////////////////////////
    void                            AddObjectHandler(const std::string& _ObjectHandlerName, const BaseObjectHandler& _ObjectHandler, bool _bForce = false);
    ////////////////////////////////////////////////////////////
    /// Get an object handler
    ///
    /// \param _ObjectHandlerName : Name of the object handler
    ///
    /// \return The object handler corresponding to the given name
    ///
    ////////////////////////////////////////////////////////////
    BaseObjectHandler*              GetObjectHandler(const std::string& _ObjectHandlerName);
    ////////////////////////////////////////////////////////////
    /// Create an object handler
    ///
    /// \param _ObjectHandlerName : Name of the object handler
    ///
    /// \return A copy of the object handler corresponding to the given name
    ///
    ////////////////////////////////////////////////////////////
    BaseObjectHandler*              CreateObjectHandler(const std::string& _ObjectHandlerName);

private:
    ////////////////////////////////////////////////////////////
    /// Structure that hold the handler to copy and the number of handlers created
    ////////////////////////////////////////////////////////////
    struct CreatedHandler {
        int                 m_iNumCreated;
        BaseObjectHandler*  m_pHandler;

        explicit CreatedHandler( BaseObjectHandler* _pHandler ) : 
            m_iNumCreated( 0 ),
            m_pHandler( _pHandler )
        {
        }

    private:
        CreatedHandler() : 
            m_iNumCreated( 0 ),
            m_pHandler( NULL )
        {
        }
    };
    typedef std::map< std::string, CreatedHandler > td_mapObjectHandler;

    td_mapObjectHandler             m_ObjectHandlers;
};


#endif // __OBJECT_HANDLER_FACTORY_HPP__